package org.springframework.security.web.context;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.log.LogMessage;
import org.springframework.security.core.context.DeferredSecurityContext;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolderStrategy;

import java.util.function.Supplier;

/**
 * @author Dillon
 * @date 2024/7/10
 * @slogan 致敬大师 致敬未来的你
 * @desc 默认延时缓存实现类，用于执行数据延时从磁盘加载到内存
 */
final class SupplierDeferredSecurityContext implements DeferredSecurityContext {

	/**
	 * 日志对象
	 */
	private static final Log logger = LogFactory.getLog(SupplierDeferredSecurityContext.class);

	/**
	 * 提供者接口，提供 SecurityContext
	 */
	private final Supplier<SecurityContext> supplier;

	/**
	 * 内存持有策略 threadLocal
	 */
	private final SecurityContextHolderStrategy strategy;

	/**
	 * 上下文接口
	 */
	private SecurityContext securityContext;

	/**
	 * 是否加载不到缓存
	 */
	private boolean missingContext;

	/**
	 * 构造函数
	 *
	 * @param supplier 缓存提供类
	 * @param strategy 内存持有策略
	 */
	SupplierDeferredSecurityContext(Supplier<SecurityContext> supplier, SecurityContextHolderStrategy strategy) {
		this.supplier = supplier;
		this.strategy = strategy;
	}

	/**
	 * 获取缓存
	 *
	 * @return SecurityContext
	 */
	@Override
	public SecurityContext get() {
		init();
		return this.securityContext;
	}

	/**
	 * 缓存是否获取不到
	 *
	 * @return 是否获取不到缓存
	 */
	@Override
	public boolean isGenerated() {
		init();
		return this.missingContext;
	}

	/**
	 * 初始化方法
	 */
	private void init() {
		// 如果已获取缓存，直接返回
		if (this.securityContext != null) {
			return;
		}
		// 尝试获取
		this.securityContext = this.supplier.get();
		// 如果获取不到 标记获取不到并创建一个空的缓存对象
		this.missingContext = (this.securityContext == null);
		if (this.missingContext) {
			this.securityContext = this.strategy.createEmptyContext();
			if (logger.isTraceEnabled()) {
				logger.trace(LogMessage.format("Created %s", this.securityContext));
			}
		}
	}

}
